Skip to content

feat(QTI): add Gap Match interaction viewer - #15214

Open
habibayman wants to merge 34 commits into
learningequality:developfrom
habibayman:feat/gap-match
Open

feat(QTI): add Gap Match interaction viewer#15214
habibayman wants to merge 34 commits into
learningequality:developfrom
habibayman:feat/gap-match

Conversation

@habibayman

@habibayman habibayman commented Aug 18, 2026

Copy link
Copy Markdown
Member

Summary

This PR adds the QTI Gap Match interaction.
Gap match asks a learner to fill blanks in a passage from a pool of words. The fixtures for it already existed but I added extra examples for the answer specific pools.

What it does

  • Renders qti-gap-match-interaction with a response pool above the passage and inline blanks in the text
  • Fill a gap by clicking a word then a gap, or a gap then a word
  • Drag a word into a gap, between gaps, or back to the pool
  • Tab reaches each gap and the arrow keys step through its options, so nothing needs a mouse
  • Clicking a filled gap empties it; dropping onto one replaces what's there
  • Restores a saved answer and reports it back for scoring

Answer-specific distractor pools

A gap can be fed by its own set of words instead of the whole pool. Picking up a word highlights the gaps that would take it
Behavior description:

  • While dragging, gaps that would reject the word are dimmed
  • Gaps that already hold a word aren't highlighted, though they can still be replaced
  • An item with no match-group behaves exactly as before, one pool feeding every gap
qti-answer-specific-pools.webm

Notable details

  • Gaps are found by walking the passage, since a gap can sit anywhere the author puts it, inside a paragraph, a table cell, a quotation
  • Gap match writes its pairs word-first, the opposite of match interaction, so useMatchRows gained an option for which end comes first. Match interaction is unaffected.
  • Gap.vue takes its attributes over rather than inheriting them. An inherited class replaces the component's own root class instead of joining it, which would break both the gap styling and the width classes.
  • qti-input-width-N sizes a blank to roughly N characters

$\color{rgba(0, 128, 0)}{\textsf{Gap match inside a table example:}}$

image

References


Reviewer guidance

  1. Navigate to http://localhost:8000/en/learn/#/qti_sandbox
  2. All of the gap match examples in the sandbox are supported and render
    but these examples don't do all what the name implies, some of these were dropped:
    • Positioning: qti-choices-top/bottom/left/right are ignored, so all four pools sit above their passage instead of beside it.
    • Container Width: data-choices-container-width is ignored. The apparent width difference comes from the fixture's own qti-layout-col5 / qti-layout-col9 wrappers.
    • Custom Messages: data-max-selections-message and data-min-selections-message are ignored, and there's no notice yet at all, so nothing is shown when a limit is hit.

AI usage

All unit tests are written by Claude in addition to the extra fixture I added

@github-actions github-actions Bot added DEV: renderers HTML5 apps, videos, exercises, etc. DEV: frontend SIZE: very large labels Aug 18, 2026
@learning-equality-bot

Copy link
Copy Markdown

👋 Hi @habibayman, thanks for contributing!

For the review process to begin, please verify that the following is satisfied:

  • Contribution is aligned with our contributing guidelines

  • Pull request description has correctly filled AI usage section & follows our AI guidance:

    AI guidance

    State explicitly whether you didn't use or used AI & how.

    If you used it, ensure that the PR is aligned with Using AI as well as our DEEP framework. DEEP asks you:

    • Disclose — Be open about when you've used AI for support.
    • Engage critically — Question what is generated. Review code for correctness and unnecessary complexity.
    • Edit — Review and refine AI output. Remove unnecessary code and verify it still works after your edits.
    • Process sharing — Explain how you used the AI so others can learn.

    Examples of good disclosures:

    "I used Claude Code to implement the component, prompting it to follow the pattern in ComponentX. I reviewed the generated code, removed unnecessary error handling, and verified the tests pass."

    "I brainstormed the approach with Gemini, then had it write failing tests for the feature. After reviewing the tests, I used Claude Code to generate the implementation. I refactored the output to reduce verbosity and ran the full test suite."

Also check that issue requirements are satisfied & you ran pre-commit locally.

Pull requests that don't follow the guidelines will be closed.

Reviewer assignment can take up to 2 weeks.

@github-actions

github-actions Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

@habibayman
habibayman marked this pull request as ready for review August 20, 2026 13:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

DEV: frontend DEV: renderers HTML5 apps, videos, exercises, etc. SIZE: very large

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Product Issue: Gap Match QTI Interaction

1 participant